#! /usr/bin/env python
# -*- coding: utf-8 -*-

from sets import Set
#globa variables
patterns = []
found_patterns = {0:[]}

hints = {}
found_hints = {}


def read_patterns_from_db():
  import psycopg2, sys

  con = None
  try:
    db = psycopg2.connect(
          host = '10.244.181.30',
          database = 'triage_tools',
          user = 'triage_agent',
          password = 'triage')
    cur = db.cursor()
    cur.execute('SELECT bt from bt_filters;')
    row = cur.fetchone()
    while row:
      patterns.append(row[0].strip())
      row = cur.fetchone()

    cur.execute('SELECT bt_hints.pattern, hints.text from bt_hints LEFT JOIN hints ON bt_hints.hint_id = hints.id;')
    row = cur.fetchone()
    while row:
#      normalized_signature = ''.join(row[0].strip().split())
#      hints[normalized_signature] = row[1].strip()
      hints[row[0].strip()] = row[1].strip()
#      print "hint signature: \"%s\"" % row[0].strip()
      row = cur.fetchone()


  except psycopg2.DatabaseError, e:
    print 'Error %s' % e
    sys.exit(1)

  finally:
    if con:
       con.close()
#endof read_patterns_from_db

def handle_thread(headline, bt_signature, bt, verboseprint):
  index = -1
  try:
   index = patterns.index(bt_signature)
#   print "skipping backtrace for %s\n" % headline
  except:
    print headline
    print bt
    verboseprint(bt_signature)
    print "\n"

  if index != -1 :
    if index in found_patterns:
      found_patterns[index].append(headline)
    else:
      found_patterns[index] = [headline]

#  print "---"
#  print "headline: %s" % headline
#  normalized_bt_signature = ''.join(bt_signature.split())
#  print "normalized_bt_signature: \"%s\"" % normalized_bt_signature
#  for i in hints.keys():
#    print "i: \"%s\"" % i
#    if i in normalized_bt_signature:
#      found_hints[hints[i]] = headline
#  print "---"

#  print "---"
#  print "headline: %s" % headline
  normalized_bt_signature = ''.join(bt_signature.split())
  for i in hints.keys():
    found_all = 1
    k = 0
    for j in i.split():
      k = normalized_bt_signature.find(j.strip(), k)
#     print "%d %s" % (k, j)
      if k == -1:
        found_all = 0
#        print "not found"
        break
    if found_all == 1:
      found_hints[hints[i]] = headline
#      print "found"
#  print "---"

#end of handle_thread

def handle_bt_all(path, verboseprint):
  status = 0 

  fileIN = open(path, "r")
  line = fileIN.readline()

  import re
  import datetime

  startMarker      = re.compile(r"Thread\s+(?P<tid>\d+)\s+.*")
  btEntry          = re.compile(r"#(?P<fid>\d+)\s+0x(?P<ptid>[\d|a-f|A-F]+)\s+in.*")

  headline     = ""
  bt_signature = ""
  bt           = ""

  while line:
    m = startMarker.match(line)
    if m:
      if bt != "" and headline != "" :
        handle_thread(headline, bt_signature.strip(), bt, verboseprint)
        bt = ""
        bt_signature = ""
      headline = line.strip()

    m = btEntry.search(line)
    if m:
      str = ""
      in_pos = line.find("in") + len("in")
      from_pos = line.find("from")
      at_pos = line.find("at")
      if from_pos != -1:
        str = line[in_pos:from_pos].strip()
      elif at_pos != -1 :
        bracket_pos = line.find("(")
        if bracket_pos != -1:
          str = line[in_pos:bracket_pos].strip() + " ()"
        else:
          str = line[in_pos:at_pos].strip()
      else:
        str = line[in_pos:].strip()
#      print "%s '%s'" % (m.group(1), str)
      bt_signature += ("'%s'\n" % str)
      bt += ("%s\n" % line.strip()) 
    
    line = fileIN.readline()
  #enf of for
  handle_thread(headline, bt_signature.strip(), bt, verboseprint)
  fileIN.close()


  verboseprint("------------------------------------------------------------")
  verboseprint("skipped threads")
  verboseprint("------------------------------------------------------------")
  for i in found_patterns.keys():
    for j in found_patterns[i]:
      verboseprint(j)
    verboseprint(patterns[i])

  print "------------------------------------------------------------"
  print "hints"
  print "------------------------------------------------------------" 
  for i in found_hints.keys():
    print "thread \"%s\" has a signature for '%s'" % (found_hints[i], i)

  return status
#end of handle_cimom_log


if __name__ == "__main__":
  from optparse import OptionParser
  parser = OptionParser()
  parser.add_option("-f", "--file", dest="filename", help="full path to file with all ECOM back traces", metavar="FILE")
  parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
  (options, args) = parser.parse_args()

#-------------------------------------------------------------------------------------------------
  if options.verbose:
    print "Source file: %s" % options.filename
    def verboseprint(*args):
        # Print each argument separately so caller doesn't need to
        # stuff everything to be printed into a single string
        for arg in args:
           print arg,
        print
  else:   
    verboseprint = lambda *a: None      # do-nothing function
#-------------------------------------------------------------------------------------------------

  if options.filename:
    import sys
    read_patterns_from_db()
    sys.exit(handle_bt_all(options.filename, verboseprint))
  else:
    parser.error("filename is not specified")

